package sopt.dev.data;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.apache.log4j.Logger;

import sopt.dev.db.DBHelper;
import sopt.dev.db.CityInfoDB.CityDBScheme;
import sopt.dev.db.ItemInfoDB.ItemDBScheme;

import android.content.ContentValues;

/**
 * @FileName  : GagebuDataModel.java
 * @Project     : Gagebu
 * @Date         : 2013. 8. 23. 
 * @작성자      : Dev
 * @변경이력 :
 * @프로그램 설명 : 도시 관련 데이터들을 관리하는 곳, 싱글톤으로 구현, 리스트 형태의 데이터를 사용하는 추상 모델 클래스 상속
 *				프로그램의 정밀도 및 확장성을 위해 제네릭을 사용하였음
 * 				리스트속의 리스트 형태로 구성 (도시 리스트 속의 아이템 리스트) 
 */
public class GagebuDataModel extends DataModel<CityVO<ItemVO>> implements ICityModel {

	private static GagebuDataModel mInstance;
	private DBHelper dbHelper = DBHelper.getInstance();

	static { mInstance = new GagebuDataModel(); }


	private GagebuDataModel() {
		setListData(new ArrayList<CityVO<ItemVO>>());
	}

	public static GagebuDataModel getInstance() {
		if (mInstance == null)
			return new GagebuDataModel();
		else
			return mInstance;
	}

	@Override
	public void addCity(CityVO<ItemVO> city) {

		if(itemList.contains(city)) {
			for(int i = 0; i < itemList.size(); ++i) {
				if(itemList.get(i).equals(city)) {
					updateCity(city, i);
				}				
			}
		} else {
			addItem(city);
		}
	}


	@Override
	public void updateCity(CityVO<ItemVO> city, int position) {
		updateItem(city, position);
	}

	@Override
	public void addItemData(String cityName, ItemVO item) {
		CityVO<ItemVO> city = findCityByName(cityName);
		int index = getCityIndex(city);
		city.addItem(item);
		itemList.set(index, city);
	}

	@Override
	public void delItemData(String cityName, ItemVO item) {
		CityVO<ItemVO> city = findCityByName(cityName);
		int index = getCityIndex(city);
		city.removeItem(item);
		itemList.set(index, city);

	}

	@Override
	public void updateItemData(String cityName, ItemVO item) {
		CityVO<ItemVO> city = findCityByName(cityName);
		int index = getCityIndex(city);
		city.updateItem(item);
		itemList.set(index, city);
	}

	@Override
	public List<ItemVO> readAllItemData(String cityName) {
		return findCityByName(cityName).getItemList();
	}

	@Override
	public CityVO<ItemVO> findCityByName(String cityName) {
		for(CityVO<ItemVO> city : itemList) {
			if(cityName.equals(((CityVO<ItemVO>) city).getCityName()))
				return (CityVO<ItemVO>) city;
		}
		return null;
	}

	@Override
	public void delCityData(CityVO<ItemVO> seekCity) {
		delItem(seekCity);
	}

	@Override
	public List<CityVO<ItemVO>> readAllCityData() {
		return (List<CityVO<ItemVO>>) itemList;
	}

	public double getSumofCity(String cityName) {
		List<ItemVO> itemList = readAllItemData(cityName);
		double sum = 0;

		for(ItemVO item : itemList) {
			sum += item.getPrice();
		}

		return sum;
	}

	/**
	 * @Method Name  : getDateListInCity
	 * @작성일   : 2013. 8. 23. 
	 * @작성자   : Dev
	 * @변경이력  :
	 * @Method 설명 : 도시의 아이템에서 날짜값들을 추출하여 중복없는 리스트 형태로 반환
	 * @param cityName
	 * @return
	 */
	public List<String> getDateListInCity(String cityName){

		List<String> dateList = new ArrayList<String>();

		// 도시의 모든 아이템 리스트
		List<ItemVO> itemList = findCityByName(cityName).getItemList();

		for(ItemVO item : itemList) {
			// 순회하면서 아이템들의 모든 날짜값들을 리스트에 추가해줌
			dateList.add(item.getDate());
		}

		// HashSet을 사용하여 중복제거(순서 보장 안됨) 후 리스트 형태로 리턴 
		return new ArrayList<String>(new HashSet<String>(dateList));
	}



	/**
	 * @Method Name  : getItemDataGroupedByDate
	 * @작성일   : 2013. 8. 23. 
	 * @작성자   : Dev
	 * @변경이력  :
	 * @Method 설명 : 도시내에서 아이템 리스트 들을 날짜 별로 그룹화 한 리스트를 반환
	 * @param cityName
	 * @return
	 */
	public List<List<ItemVO>> getItemDataGroupedByDate(String cityName) {

		List<List<ItemVO>> totalItemListGroupedByDate = new ArrayList<List<ItemVO>>();

		// 아이템에서 추출한 중복없는 날짜들을 순회하면서
		for(String date : getDateListInCity(cityName)) {

			List<ItemVO> itemListGroupedByDate = new ArrayList<ItemVO>();

			// 아이템들 중
			for(ItemVO item : readAllItemData(cityName)) {

				// 추출한 날짜와 같은 날짜를 가지는 아이템들을
				if(date.equals(item.getDate())) {
					// 날짜별 그룹화된 리스트에 추가
					itemListGroupedByDate.add(item);
				}
			}
			// 날짜로 그룹화 된 리스트들을 리스트로 wrapping
			totalItemListGroupedByDate.add(itemListGroupedByDate);
		}

		return totalItemListGroupedByDate;		
	}




	@Override
	public void extractDatafromDB() {
		itemList = dbHelper.getAllCityInfo();
	}


	@Override
	public synchronized void saveToDB() {

		for(CityVO<ItemVO> city : itemList) {
			ContentValues cityCV = new ContentValues();

			cityCV.put(CityDBScheme.COLUMN_CURRENCY, city.getCityMoney());
			cityCV.put(CityDBScheme.COLUMN_CITYNAME, city.getCityName());
			cityCV.put(CityDBScheme.COLUMN_IMG_PATH, city.getPicPath());
			cityCV.put(CityDBScheme.COLUMN_INDATE, city.getInString());
			cityCV.put(CityDBScheme.COLUMN_OUTDATE, city.getOutString());
		
			if(	dbHelper.update(CityDBScheme.TABLE_NAME, cityCV, 
					CityDBScheme.COLUMN_CITYNAME + " = ?", new String[]{city.getCityName()}) == 0) {
				
				dbHelper.insert(CityDBScheme.TABLE_NAME, cityCV);
			}

			ArrayList<ItemVO> items = city.getItemList();
			if(items != null) {

				for(ItemVO item : items) {
					ContentValues itemCV = new ContentValues();

					itemCV.put(ItemDBScheme.COLUMN_CITYNAME, city.getCityName());
					itemCV.put(ItemDBScheme.COLUMN_COMMENT, item.getComment());
					itemCV.put(ItemDBScheme.COLUMN_DATE, item.getDate());
					itemCV.put(ItemDBScheme.COLUMN_IMGPATH, item.getPicPath());
					itemCV.put(ItemDBScheme.COLUMN_NAME, item.getName());
					itemCV.put(ItemDBScheme.COLUMN_PRICE, item.getPrice());

					if( dbHelper.update(ItemDBScheme.TABLE_NAME, itemCV, 
							ItemDBScheme.COLUMN_NAME + " = ?", new String[] { item.getName() }) == 0 ) { 
						
						 dbHelper.insert(ItemDBScheme.TABLE_NAME, itemCV);
					}
				}
			}

		}

	}



	@Override
	public int getCityIndex(CityVO<ItemVO> city) {

		for(int i = 0; i < itemList.size(); ++i) {
			if( itemList.get(i).equals(city) )				
				return i;			
		}
		return 0;
	}

}
